import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
import matplotlib.pyplot as plt

# 设置中文字体为黑体，用来正常显示中文标签，并设置能正常显示负号
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


# 函数用于加载数据，添加异常处理
def load_data(url, columns):
    try:
        data = pd.read_csv(url, header=None, names=columns)
        return data
    except Exception as e:
        print(f"读取数据出现错误: {e}")
        return None


# 函数用于筛选指定类别数据
def filter_data_by_class(data, target_classes):
    filtered = data[data['Class'].isin(target_classes)]
    X = filtered.iloc[:, 1:]
    y = filtered['Class']
    return X, y


# 函数用于执行PCA降维
def perform_pca(X, n_components=2):
    pca = PCA(n_components=n_components)
    X_pca = pca.fit_transform(X)
    return X_pca


# 函数用于执行LDA降维
def perform_lda(X, y, n_components=1):
    lda = LDA(n_components=n_components)
    X_lda = lda.fit_transform(X, y)
    return X_lda


# 函数用于可视化PCA降维结果
def visualize_pca(X_pca, y):
    plt.figure(figsize=(8, 6))
    plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='viridis', edgecolor='k', s=50)
    plt.title('PCA: 降维到二维的散点图')
    plt.xlabel('主成分 1')
    plt.ylabel('主成分 2')
    plt.colorbar(label='类别标签')
    plt.grid()
    plt.show()


# 函数用于可视化LDA降维结果
def visualize_lda(X_lda, y):
    plt.figure(figsize=(8, 3))
    plt.scatter(X_lda, [0] * len(X_lda), c=y, cmap='viridis', edgecolor='k', s=50)
    plt.title('LDA: 降维到一维的散点图')
    plt.xlabel('线性判别 1')
    plt.yticks([])
    plt.colorbar(label='类别标签')
    plt.grid()
    plt.show()


if __name__ == "__main__":
    # 步骤 1：加载数据
    url = "https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data"
    columns = ['Class', 'Alcohol', 'Malic_acid', 'Ash', 'Alcalinity_of_ash', 'Magnesium',
               'Total_phenols', 'Flavanoids', 'Nonflavanoid_phenols', 'Proanthocyanins',
               'Color_intensity', 'Hue', 'OD280/OD315', 'Proline']
    data = load_data(url, columns)
    if data is None:
        print("数据加载失败，程序终止。")
    else:
        # 筛选类别1和类别2的数据
        X, y = filter_data_by_class(data, [1, 2])

        # PCA降维到二维
        X_pca = perform_pca(X)
        print("PCA降维后的二维特征：")
        print(X_pca)

        # LDA降维到一维
        X_lda = perform_lda(X, y)
        print("LDA降维后的一维特征：")
        print(X_lda)

        # 数据可视化
        # PCA 可视化
        visualize_pca(X_pca, y)

        # LDA 可视化
        visualize_lda(X_lda, y)